package com.twb.fileCenter.controller;

import com.twb.core.base.Result;
import com.twb.core.base.controller.BaseController;
import com.twb.core.security.annotation.Auth;
import com.twb.core.util.BeanUtils;
import com.twb.core.util.Results;
import com.twb.core.util.SpringUtil;
import com.twb.fileCenter.config.FileCenterProperties;
import com.twb.fileCenter.constants.FileCenterConstants;
import com.twb.fileCenter.entity.dto.ImportExcelDto;
import com.twb.fileCenter.entity.dto.UploadFilesDto;
import com.twb.fileCenter.entity.vo.UploadBase64Vo;
import com.twb.fileCenter.util.UploadFileUtil;
import com.twb.system.entity.twbEnclosure.TwbEnclosure;
import com.twb.system.entity.twbEnclosure.dto.ListServerFilesDto;
import com.twb.system.entity.twbEnclosure.vo.SaveTwbEnclosureVo;
import com.twb.system.entity.twbEnclosure.vo.SearchTwbEnclosureVo;
import com.twb.system.service.ITwbEnclosureService;
import com.twb.system.service.impl.TwbEnclosureService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName FileCenterController
 * @Description 文件服务管理接口
 * @author DSY
 * @date 2018年12月14日 下午4:47:29
 */
@RestController
@RequestMapping("/fileCenter")
@Api(value = "FileCenterController", tags = "文件服务管理接口")
public class FileCenterController extends BaseController {
	private Logger logger = LoggerFactory.getLogger(FileCenterController.class);

	@Autowired
	FileCenterProperties fileCenterProperties;

	@Autowired
	ITwbEnclosureService twbEnclosureService;
	

	/**
	 * @Title  uploadFiles
	 * @Description 文件上传接口（支持多文件上传）
	 * @param folder
	 * @param request
	 * @return
	 * @throws Exception
	 * @author DSY
	 * @date 2018年12月17日 下午12:35:46
	 */
	@Auth(verifyURL = false)
	@PostMapping("/uploadFiles")
	@ApiOperation(value = "文件上传接口（支持多文件上传）")
	public Result<List<UploadFilesDto>> uploadFiles(HttpServletRequest request) throws Exception {
		/*
		 * request.setCharacterEncoding("UTF-8");
		 * 
		 * List<UploadFilesDto> results = new ArrayList<UploadFilesDto>(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 * 
		 * if (StringUtils.isBlank(folder)) { folder = "temp";// 避免前台没有传递这个参数的时候会报错 } else { folder = URLDecoder.decode(folder, "UTF-8");// 中文转码（对应jsp：encodeURI("中文")） } String fileServerPath = fileCenterProperties.getFileServerPath(); if(StringUtils.isBlank(fileServerPath)) { fileServerPath = new File(request.getSession().getServletContext().getRealPath("/")).getParent();// 当前WEB环境的上层目录 } String uploadPath = fileCenterProperties.getUploadPath(); String fileServerUrl = fileCenterProperties.getFileServerUrl(); boolean useFtpServer = fileCenterProperties.isUseFtpServer(); String realPath = fileServerPath + uploadPath + "/" +folder + "/";
		 * 
		 * if(!useFtpServer){ File up = new File(realPath); if (!up.exists()) { up.mkdirs(); } }
		 * 
		 *//** 页面控件的文件流* *//*
							 * MultipartFile file = null; Map<String, MultipartFile> map = multipartRequest.getFileMap(); for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) { UploadFilesDto dto = new UploadFilesDto(); Object obj = i.next(); file = (MultipartFile) map.get(obj); if (file != null) { //文件类型 String fileType = file.getContentType(); // 取得当前上传文件的文件名称 String originalFileName = file.getOriginalFilename(); //文件格式后缀 String extName = FilenameUtils.getExtension(originalFileName); // 本地上传图片方式 String fileName = UUID.randomUUID().toString().replace("-", "");
							 * 
							 * File dest = new File(realPath + fileName +"."+ extName); boolean success = false; try { if(useFtpServer){ //获取输入流，用于将文件上传ftp服务器 InputStream inputStream = file.getInputStream(); success = FtpUtil.uploadFile(realPath, fileName +"."+ extName, inputStream); }else{ file.transferTo(dest); success = true; } } catch (IOException e) { logger.error(e.toString(), e); success = false; } dto.setId(fileName); dto.setSuccess(success); dto.setFileType(fileType); dto.setPath(uploadPath + "/" +folder + "/" + fileName +"."+ extName); dto.setUrl(fileServerUrl+uploadPath + "/" +folder + "/" + fileName +"."+ extName); dto.setNewName(fileName +"."+
							 * extName); dto.setOldName(originalFileName);
							 * 
							 * results.add(dto); } }
							 */
		List<UploadFilesDto> list = UploadFileUtil.uploadFile(fileCenterProperties, request);
		return Results.successWithData(list);
	}

	/**
	 * @Title  importExcel
	 * @Description 导入excle
	 * @param folder
	 * @param request
	 * @return
	 * @author DSY
	 * @date 2019年1月15日 下午12:28:39
	 */
	@Auth(verifyURL = false)
	@PostMapping("/importExcel")
	@ApiOperation(value = "导入excel")
	public Result<ImportExcelDto> importExcel(@ApiParam(value = "folder", name = "文件夹名称，默认temp", required = false) String folder, HttpServletRequest request) {
		try {
			long start = System.currentTimeMillis();
			ImportExcelDto dto = null;// ImportExcelUtil.importExcel(fileCenterProperties, folder, request);
			long end = System.currentTimeMillis();
			logger.debug("导入excel用时" + (end - start) + "毫秒");
			return Results.successWithData(dto);
		} catch (Exception e) {
			return Results.failure("导入失败");
		}
	}

	/**
	 * @Title base64Upload
	 * @Description 上传图片，base64数据格式
	 * @param folder
	 * @param request
	 * @return
	 * @throws Exception
	 * @author DHL
	 * @date 2020年10月15日 下午1:35:09
	 */
	@Auth(verifyURL = false)
	@PostMapping("/base64Upload")
	@ApiOperation(value = "文件上传接口（支持多文件上传）")
	public Result<List<UploadFilesDto>> base64Upload(@ApiParam(value = "base64Vo", name = "Base64图片集合", required = false) @RequestBody List<UploadBase64Vo> base64List, HttpServletRequest request) throws Exception {

		List<UploadFilesDto> results = new ArrayList<UploadFilesDto>();

		if (CollectionUtils.isNotEmpty(base64List)) {
			for (UploadBase64Vo base64Vo : base64List) {

				// 当前循环文件上传结果
				UploadFilesDto dto = new UploadFilesDto();

				String base64Data = base64Vo.getBase64();
				String dataPrix = "";
				String data = "";
				if (base64Data == null || "".equals(base64Data)) {

					dto.setSuccess(false);
					dto.setMsg("上传失败, Base64 内容为空");
				} else {
					String[] d = base64Data.split("base64,");
					if (d != null && d.length == 2) {
						dataPrix = d[0];
						data = d[1];
					} else {

						dto.setSuccess(false);
						dto.setMsg("上传失败, 数据不合法");
					}
				}

				String suffix = "";
				if ("data:image/jpeg;".equalsIgnoreCase(dataPrix)) {
					// 编码的jpeg图片数据
					suffix = ".jpg";
					base64Vo.setType("image/jpg");
				} else if ("data:image/x-icon;".equalsIgnoreCase(dataPrix)) {
					// 编码的icon图片数据
					suffix = ".ico";
					base64Vo.setType("image/icon");
				} else if ("data:image/gif;".equalsIgnoreCase(dataPrix)) {
					// 编码的gif图片数据
					suffix = ".gif";
					base64Vo.setType("image/gif");
				} else if ("data:image/png;".equalsIgnoreCase(dataPrix)) {
					// 编码的png图片数据
					suffix = ".png";
					base64Vo.setType("image/png");
				} else {

					dto.setSuccess(false);
					dto.setMsg("上传失败, 上传图片格式不合法");
				}

				// 写入服务器文件名称
				String tempFileName = UUID.randomUUID().toString().replace("-", "") + suffix;

				// 因为BASE64Decoder的jar问题，此处使用spring框架提供的工具包
				byte[] bs = Base64Utils.decodeFromString(data);

				try {

					// 前台传递过来的文件夹参数，如果有就在这个目录里面保存文件
					String fileFolder = base64Vo.getFolder();

					if (StringUtils.isBlank(fileFolder)) {
						// 避免前台没有传递这个参数的时候会报错
						fileFolder = "temp/base64";
					} else {
						// 中文转码（对应jsp：encodeURI("中文")）
						fileFolder = URLDecoder.decode(fileFolder, "UTF-8");
					}

					// 上传的物理路径
					String fileServerPath = fileCenterProperties.getFileServerPath();

					if (StringUtils.isBlank(fileServerPath)) {
						// 当前WEB环境的上层目录
						fileServerPath = new File(request.getSession().getServletContext().getRealPath("/")).getParent();
					}

					String uploadPath = fileCenterProperties.getUploadPath();
					String fileServerUrl = fileCenterProperties.getFileServerUrl();
					String serverType = fileCenterProperties.getServerType();
					String realPath = fileServerPath + uploadPath + "/" + fileFolder + "/";

					if (serverType.equals(FileCenterConstants.serverType.LOCAL)) {
						File up = new File(realPath);
						if (!up.exists()) {
							up.mkdirs();
						}
					}

					FileUtils.writeByteArrayToFile(new File(realPath, tempFileName), bs);

					dto.setFileId(tempFileName);
					dto.setSuccess(true);
					dto.setFileType(base64Vo.getType());
					dto.setPath(uploadPath + "/" + fileFolder + "/" + tempFileName);
					dto.setUrl(fileServerUrl + uploadPath + "/" + fileFolder + "/" + tempFileName);
					dto.setNewName(tempFileName);
					dto.setOldName(base64Vo.getName());

					// 附件保存到数据库
					if (fileCenterProperties.isUploadToDb()) {
						ITwbEnclosureService enclosureService = SpringUtil.getBean(TwbEnclosureService.class);
						SaveTwbEnclosureVo vo = new SaveTwbEnclosureVo();
						vo.setBasePath(dto.getPath());
						vo.setOrigName(dto.getOldName());
						vo.setName(dto.getNewName());
						vo.setFileType(dto.getFileType());
						vo.setFilePath(dto.getUrl());
						TwbEnclosure result = enclosureService.saveTwbEnclosure(vo);
						String fileId = result.getId();
						dto.setFileId(fileId);
					}

					results.add(dto);

				} catch (Exception e) {
					dto.setSuccess(false);
					dto.setMsg(e.getMessage());
					logger.error("======Base64上传失败:" + e.getMessage());
				}

			}
		}

		return Results.successWithData(results);
	}

	/**
	 * @Title download
	 * @Description 文件下载
	 * @param fileId
	 * @param request
	 * @param response
	 * @return
	 * @author DHL
	 * @date 2021年6月1日 下午4:39:54
	 */
	@Auth(verifyURL = false, verifyToken = false)
	@GetMapping("/download")
	@ApiOperation(value = "文件下载")
	public Result<String> download(String fileId, HttpServletRequest request, HttpServletResponse response) {
		if (StringUtils.isBlank(fileId)) {
			return Results.failure("下载失败");
		}

		response.setContentType("text/html;charset=UTF-8");

		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;

		try {
			request.setCharacterEncoding("UTF-8");

			SearchTwbEnclosureVo searchTwbEnclosureVo = new SearchTwbEnclosureVo();
			searchTwbEnclosureVo.setFileIds(fileId);

			// 此处使用的配置文件里面取出的文件服务器地址,拼凑成完整的文件服务器上的文件路径
			List<ListServerFilesDto> listServerFiles = twbEnclosureService.listServerFiles(searchTwbEnclosureVo);

			TwbEnclosure twbEnclosure = new TwbEnclosure();

			if (CollectionUtils.isNotEmpty(listServerFiles)) {
				if (listServerFiles.size() > 1) {
					return Results.failure("下载失败");
				}

				ListServerFilesDto listServerFilesDto = listServerFiles.get(0);

				if (listServerFilesDto == null) {
					return Results.failure("下载失败");
				}

				BeanUtils.copyNotNullProperties(listServerFilesDto, twbEnclosure);
			}

			String downLoadPath = twbEnclosure.getFilePath();

			response.setContentType("application/octet-stream");
			response.reset();// 清除response中的缓存

			// 根据网络文件地址创建URL
			URL url = new URL(downLoadPath);

			// 获取此路径的连接
			URLConnection conn = url.openConnection();

			// 获取文件大小
			Long fileLength = conn.getContentLengthLong();

			// 设置reponse响应头，真实文件名重命名，就是在这里设置，设置编码
			response.setHeader("Content-disposition", "attachment; filename=" + new String(twbEnclosure.getOrigName().getBytes("utf-8"), "ISO8859-1"));
			response.setHeader("Content-Length", String.valueOf(fileLength));
			response.setHeader("Access-Control-Allow-Origin", "*");

			// 构造读取流
			bis = new BufferedInputStream(conn.getInputStream());
			// 构造输出流
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[1024];
			int bytesRead;
			// 每次读取缓存大小的流，写到输出流
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
			response.flushBuffer();// 将所有的读取的流返回给客户端
			bis.close();
			bos.close();

		} catch (Exception e) {
			e.printStackTrace();
			return Results.failure("下载失败");
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return Results.success("下载成功");
	}
}
